package com.jyt.motor.util;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class CRC16 {
    static byte[] crc16_tab_h = {(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40};

    static byte[] crc16_tab_l = {(byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12,
            (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7,
            (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74,
            (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98, (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D,
            (byte) 0x4C, (byte) 0x8C, (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40};

    /**
     * 计算CRC16校验
     *
     * @param data 需要计算的数组
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data) {
        return calcCrc16(data, 0, data.length);
    }

    /**
     * 计算CRC16校验
     *
     * @param data   需要计算的数组
     * @param offset 起始位置
     * @param len    长度
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data, int offset, int len) {
        return calcCrc16(data, offset, len, 0xffff);
    }

    /**
     * 计算CRC16校验
     *
     * @param data   需要计算的数组
     * @param offset 起始位置
     * @param len    长度
     * @param preval 之前的校验值
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data, int offset, int len, int preval) {
        int ucCRCHi = (preval & 0xff00) >> 8;
        int ucCRCLo = preval & 0x00ff;
        int iIndex;
        for (int i = 0; i < len; ++i) {
            iIndex = (ucCRCLo ^ data[offset + i]) & 0x00ff;
            ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex];
            ucCRCHi = crc16_tab_l[iIndex];
        }

        //return ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;
        return ((ucCRCLo & 0x00ff) << 8) | (ucCRCHi & 0x00ff) & 0xffff;
        //return ( (ucCRCHi & 0x0000FF00) >> 8) | ( (ucCRCLo & 0x000000FF ) << 8);
    }

    public static byte[] int2Bytes(int integer) {
        byte[] bytes = new byte[2];
       // bytes[0] = (byte) (integer >> 24);
       // bytes[1] = (byte) (integer >> 16);
        bytes[0] = (byte) (integer >> 8);
        bytes[1] = (byte) integer;
        return bytes;
    }
    

    public static int bytes2Int(byte[] bytes) {
        int int1 = 0;
        int int2 = 0;
        int int3 = 0;
        int int4 = 0;
        if (bytes.length >= 4) {
            int1 = bytes[3] & 0xff;
        }
        if (bytes.length >= 3) {
            int2 = (bytes[2] & 0xff) << 8;
        }
        if (bytes.length >= 2) {
            int3 = (bytes[1] & 0xff) << 16;
        }
        if (bytes.length >= 1) {
            int4 = (bytes[0] & 0xff) << 24;
        }
        return int1 | int2 | int3 | int4;
    }
    
    public static int bytes2Int2(byte[] bytes) {
        int int1 = 0;
        int int2 = 0;
        if (bytes.length >= 2) {
            int1 = bytes[1] & 0xff;
        }
        if (bytes.length >= 1) {
            int2 = (bytes[0] & 0xff) << 8;
        }
        return int1 | int2 ;
    }

    public static String bytesToString(byte[] bytes) {
        char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        // 一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 3];
        int a = 0;
        int index = 0;
        for (byte b : bytes) { // 使用除与取余进行转换
            if (b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }
            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
            buf[index++] = ' ';
        }
        return new String(buf);
    }

    public static byte[] command2Bytes(String command) {
        String[] arrs = command.split(" ");
        byte[] bytes = new byte[arrs.length];
        for (int i = 0; i < arrs.length; i++) {
            String hex = arrs[i];
            byte b = (byte) Integer.parseInt(hex, 16);
            bytes[i] = b;
        }
        return bytes;
    }

    public static String list2String(List<Integer> ints) {
        if (ints == null || ints.size() == 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer("[");
        for (Integer i : ints) {
            sb.append(i + ",");
        }
        return sb.substring(0, sb.length() - 1) + "]";
    }

    public static String map2String(Map<String, Object> map) {
        if (map != null && map.size() > 0) {
            StringBuffer str = new StringBuffer("");
            str.append("{\"");
            for (String key : map.keySet()) {
                str.append(key);
                if (key.equals("dateTime") || key.equals("msg")) {
                    str.append("\":\"");
                    str.append(map.get(key).toString());
                    str.append("\",\"");
                } else {
                    str.append("\":");
                    str.append(map.get(key).toString());
                    str.append(",\"");
                }

            }
            return str.substring(0, str.length() - 2) + "}";
        } else {
            return "";
        }

    }
    
   
    /**
	 * 字节数组转float
	 * 采用IEEE 754标准
	 * @param bytes
	 * @return
	 */
	public static float bytes2Float(byte[] bytes){
		//获取 字节数组转化成的2进制字符串
		String BinaryStr = bytes2BinaryStr(bytes);
		//符号位S
		Long s = Long.parseLong(BinaryStr.substring(0, 1));
		//指数位E
		Long e = Long.parseLong(BinaryStr.substring(1, 9),2);
		//位数M
		String M = BinaryStr.substring(9);
		float m = 0,a,b;
		for(int i=0;i<M.length();i++){
			a = Integer.valueOf(M.charAt(i)+"");
			b = (float) Math.pow(2, i+1);
			m =m + (a/b);
		}
		Float f = (float) ((Math.pow(-1, s)) * (1+m) * (Math.pow(2,(e-127))));
		return f;
	}
	/**
	 * 将字节数组转换成2进制字符串
	 * @param bytes
	 * @return
	 */
	public static String bytes2BinaryStr(byte[] bytes){
		StringBuffer binaryStr = new StringBuffer();
		for(int i=0;i<bytes.length;i++){
			String str = Integer.toBinaryString((bytes[i] & 0xFF) + 0x100).substring(1);
			binaryStr.append(str);
		}
		return binaryStr.toString();
	}
	
 public static String intTo16String4(int num)
 {
     String hex = Integer.toHexString(num);
     return padRight(hex,4,'0');
 }
    public static String padLeft(String src, int len, char ch) {
        int diff = len - src.length();
        if (diff <= 0) {
            return src;
        }

        char[] charr = new char[len];
        System.arraycopy(src.toCharArray(), 0, charr, 0, src.length());
        for (int i = src.length(); i < len; i++) {
            charr[i] = ch;
        }
        return new String(charr);
    }

    public static String padRight(String src, int len, char ch) {
        int diff = len - src.length();
        if (diff <= 0) {
            return src;
        }

        char[] charr = new char[len];
        System.arraycopy(src.toCharArray(), 0, charr, diff, src.length());
        for (int i = 0; i < diff; i++) {
            charr[i] = ch;
        }
        return new String(charr);
    }
	
	public static long parseLong(String s, int radix) {
		if (s == null) {
			throw new NumberFormatException(s);
		}
 
		if (radix < Character.MIN_RADIX) {
			throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX");
		}
		if (radix > Character.MAX_RADIX) {
			throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX");
		}
 
		long result = 0;
		boolean negative = false;
		int i = 0, len = s.length();
		long limit = -Long.MAX_VALUE;
		long multmin;
		int digit;
 
		if (len > 0) {
			char firstChar = s.charAt(0);
			if (firstChar < '0') { // Possible leading "+" or "-"
				if (firstChar == '-') {
					negative = true;
					limit = Long.MIN_VALUE;
				} else if (firstChar != '+')
					throw new NumberFormatException(s);
 
				if (len == 1) // Cannot have lone "+" or "-"
					throw new NumberFormatException(s);
				i++;
			}
			multmin = limit / radix;
			while (i < len) {
				// Accumulating negatively avoids surprises near MAX_VALUE
				digit = Character.digit(s.charAt(i++), radix);
				if (digit < 0) {
					throw new NumberFormatException(s);
				}
				if (result < multmin) {
					throw new NumberFormatException(s);
				}
				result *= radix;
				if (result < limit + digit) {
					throw new NumberFormatException(s);
				}
				result -= digit;
			}
		} else {
			throw new NumberFormatException(s);
		}
		return negative ? result : -result;
	}

    public static boolean checkCRC4(byte[] content) {
        int res = CRC16.calcCrc16(content, 0, content.length - 2);
        byte[] bb = CRC16.int2Bytes(res);
        if (bb[2] == content[content.length - 2] && bb[3] == content[content.length - 1]) {
            return true;
        }
        return false;
    }
    public static boolean checkCRC2(byte[] content) {
        int res = CRC16.calcCrc16(content, 0, content.length - 2);
        byte[] bb = CRC16.int2Bytes(res);
        if (bb[0] == content[content.length - 2] && bb[1] == content[content.length - 1]) {
            return true;
        }
        return false;
    }
    public static int[] byte2Info(byte[] bytes) {
        if (bytes.length == 4) {
            int[] data = new int[2];
            for (int i = 0; i < 2; i++) {
                Integer k = Integer.parseInt(CRC16.bytesToString(Arrays.copyOfRange(bytes, i * 2, (i + 1) * 2)).replace(" ", "").replace("-", ""), 16);
                data[i]=k;
            }
            return data;
        }else if(bytes.length == 16)
        {
            int[] data = new int[8];
            for (int i = 0; i < 8; i++) {
                Integer k = Integer.parseInt(CRC16.bytesToString(Arrays.copyOfRange(bytes, i * 2, (i + 1) * 2)).replace(" ", "").replace("-", ""), 16);
                data[i]=k;
            }
            return data;
        }
        return new int[0];
    }


    // 测试
    public static void main(String[] args) {

        System.out.println(intTo16String4(33));
    // 0x02 05 00 03 FF 00 , crc16=7C 09     31 00 0C 
   // int crc = CRC16.calcCrc16(new byte[] { 0x02, 0x05, 0x00, 0x03, (byte) 0xff, 0x00 });
    //	byte[] aaaa=new byte[] { 0x01,0x04,0x10,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFB,(byte)0x0F,(byte)0x7E,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD };
    //    int crc = CRC16.calcCrc16(aaaa);
      //  System.out.println(crc);  00  00 0C 3F 31
   //     System.out.println(bytes2Int((new byte[]{ 0x00, 0x0C, 0x3F, 0x31})));
    	//System.out.println(bytes2Int2(new byte[]{0x00, 0x0A}));
//        byte[] aa=int2Bytes(crc);
//        System.out.println(""+(bytes2Int(aa)));
//        String a=String.format("%04X", crc);
//        System.out.println(a);
//        String regex = "(.{2})";
//        a = a.replaceAll (regex, "$1 ");
//        System.out.println(a);
//        System.out.println(MotorDataServiceImpl.checkCRC(new byte[] { 0x01,0x04,0x10,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFB,(byte)0x0F,(byte)0x7E,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,(byte)0xFF,(byte)0xFD,0x6E,(byte)0xEA }));
  }


}
